/**
 * Project Name:boar-deploy-jar 
 * File Name:DeployMessageService.java 
 * Date:2017年6月27日
 */
package com.boarsoft.boar.log;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.websocket.Session;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.boarsoft.boar.BaseConfig;
import com.boarsoft.boar.deploy.DeployConfig;
import com.boarsoft.boar.deploy.common.Constants;
import com.boarsoft.common.Util;
import com.boarsoft.common.util.FileUtil;
import com.boarsoft.common.util.JsonUtil;
import com.boarsoft.message.bean.Message;
import com.boarsoft.message.core.MessageService;
import com.boarsoft.web.websocket.WebsocketEndpoint;
import com.boarsoft.web.websocket.WebsocketMessage;

/**
 * 部署消息存储和推送服务
 * 
 * @author YangLiu
 * @CreateDate 2017年6月27日 下午5:26:52
 * @version 1.0
 * 
 * @UpdateUser 修改人名称
 * @UpdateDate 2017年6月27日 下午5:26:52
 * @UpdateRemark 修改具体的内容
 */
@Component("deployLogReceiver")
public class DeployLogReceiver implements MessageService {
	
	private static Logger logger = LoggerFactory.getLogger(DeployLogReceiver.class); 
	// 日志显示时文件后缀
	private static String LOG_SHOW_SUFFIX = ".htm";

	/* (non-Javadoc)
	 * @see com.boarsoft.message.core.MessageService#put(com.boarsoft.message.bean.Message)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public void put(Message logMsg) throws Exception {
		String logKey = logMsg.getKey();
		if (Util.strIsEmpty(logKey)) {
			return;
		}
		Map<String, String> keys = (Map<String, String>) JsonUtil.parseObject(logKey, Map.class);
		
		logger.info("Received deploy log: {}", JsonUtil.from(keys));
		// 1, 将日志推送给前台展示给用户
		showLogs(logMsg, keys.get("sessionId"), keys.get("env"), keys.get("taskType"));
		
		// 2, 将日志记录到以logPath为文件相对路径名的日志文件中
		// 例如：部署日志的path为"deploy/00076c7e-755d-4f00-a3d4-58a58697e5fb",
		// 		那么当前部署日志将被记录到deploy/00076c7e-755d-4f00-a3d4-58a58697e5fb.htm这个文件中
		String armFile = keys.get("logPath");
		if (Util.strIsNotEmpty(armFile)) {
			recordLogs(logMsg, keys.get("logPath"));
		}
	}

	/**
	 * @param logMsg
	 * @param userSessionId 用户本次操作页面的websocket session id
	 * @param env 
	 * @param taskType 
	 */
	private void showLogs(Message logMsg, String userSessionId, String env, String taskType) {
		Session session = WebsocketEndpoint.getSession(userSessionId);
		String fromIp = logMsg.getFromAddr();
		Map<String, String> data = new HashMap<>();
		if (Util.strIsNotEmpty(fromIp) && fromIp.indexOf(":") > 0) {
			fromIp = fromIp.substring(0, fromIp.indexOf(":"));
		}
		if (session != null) {
//			MsgBean.sendMsg(session, 
//					JsonUtil.from(new LogMsg(
//							MsgBean.MSG_TYPE_EXEC_LOG,
//							(String)logMsg.getContent(), 
//							Util.date2str(new Date(logMsg.getTime()), Util.STDDTF), 
//							fromIp)));
			data.put("ip", fromIp);
			data.put("log", (String)logMsg.getContent());
			data.put("env", env);
			WebsocketMessage log = new WebsocketMessage();
			log.setGroup(taskType);
			log.setCode("log");
			log.setData(JsonUtil.from(data));
			WebsocketEndpoint.send(log, userSessionId);
		}
	}
	
	/**
	 * @param logMsg
	 * @param armFile 写入日志的目标文件相对路径
	 */
	private void recordLogs(Message logMsg, String armFile) {
		// 获取日志消息等来源服务器
		String distinctIp = logMsg.getFromAddr();
		if(distinctIp == null) {
			distinctIp = "";
			logger.debug("log comes from an unknown server");
		} else {
			if (distinctIp.indexOf(":") > 0) {
				distinctIp = distinctIp.substring(0, distinctIp.indexOf(":"));
			}
			if (DeployConfig.COMPILE_SERVER_ADDRESS.equals(distinctIp)) {
				distinctIp = "";
				logger.debug("log comes from compile server, so write the log to general file.");
			}
		}
		
		String date = Util.date2str(new Date());
		StringBuffer gnrLog = new StringBuffer(BaseConfig.PATH_PUBLIC);
		gnrLog.append(File.separator).append(Constants.DIR_LOGS).append(File.separator)
		.append(date).append(File.separator)
		.append(armFile).append(LOG_SHOW_SUFFIX);
		if (Util.strIsNotEmpty(distinctIp)) {
			logger.debug("log comes from deploy server {}, so write the log to file for each server.", distinctIp);
			// 除打包服务器外、其他部署服务器的日志文件名
			StringBuffer svrlog = new StringBuffer(BaseConfig.PATH_PUBLIC);
			svrlog.append(File.separator).append(Constants.DIR_LOGS).append(File.separator)
			.append(date).append(File.separator)
			.append(armFile).append("_").append(distinctIp).append(LOG_SHOW_SUFFIX);
			File svrLogFile = new File(svrlog.toString());
			// 产生第一条部署服务器日志时，将服务器日志链接加入到总体日志文件中
			if (!svrLogFile.exists()) {
				StringBuffer svrLogLink = new StringBuffer();
				svrLogLink.append("<a href=\"../").append(armFile).append("_").append(distinctIp).append(LOG_SHOW_SUFFIX).append("\">");
				svrLogLink.append("Log from server [").append(distinctIp).append("]");
				svrLogLink.append("</a>");
				writeLogs(gnrLog.toString(), svrLogLink.toString());
			}
			// 将日志记录写入到每个服务器的日志文件中
			writeLogs(svrlog.toString(), (String) logMsg.getContent());
		} else {
			// 将日志写入到总体日志文件中
			writeLogs(gnrLog.toString(), (String) logMsg.getContent());
		}
	}

	/**
	 * 
	 */
	private void writeLogs(String abFileName, String log) {
		File logFile = new File(abFileName);
		if (!logFile.getParentFile().exists()) {
			logFile.getParentFile().mkdirs();
		}
		try {
			if (!logFile.exists()) {
				StringBuffer htmlHeader = new StringBuffer("<HTML>\n");
				htmlHeader.append("<HEADER><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" /></HEADER>\n");
				htmlHeader.append("<BODY>\n");
				htmlHeader.append("<PRE>\n");
				FileUtil.write(logFile, htmlHeader.toString(), true);
			}
			FileUtil.write(logFile, log, true);
		} catch (FileNotFoundException e) {
			logger.error("Error to record log content [{}] to [{}] for ", log, logFile.getAbsolutePath(), e);
		}
	}

}
